import isPlainObject from 'lodash/isPlainObject';
import { history as router } from 'umi';
import { parse } from 'qs';
import moment from 'moment';
import pathRegexp from 'path-to-regexp';
import { isNil } from 'lodash'
import { BaseTree } from '@/common/declare';

// eslint-disable-next-line max-len, no-useless-escape
const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;

const isUrl = (path: string): boolean => reg.test(path);

/**
 * 删除含有 null 或者 undefined 的字段
 * @param data 要检测的数据
 */
function deleteNullOrUndefinedField(data: object) {
  return Object.keys(data).reduce((pre, key) => {
    let item = data[key];
    if (isPlainObject(item)) {
      item = deleteNullOrUndefinedField(item);
    }
    if (!(item == null)) {
      pre[key] = item; // eslint-disable-line no-param-reassign
    }
    return pre;
  }, {});
}

function replaceRouter(redirect: string) {
  router.replace(redirect || '/');
}

function getPageQuery() {
  return parse(window.location.search, {
    ignoreQueryPrefix: true,
  });
}

function deepFlatten<T>(arr: T[]): T[] {
  const ret: T[] = [];
  return ret.concat(...arr.map((v) => (Array.isArray(v) ? deepFlatten(v) : v)));
}

function flatTree<T, K extends keyof T>(arr: T[], path: K): T[] {
  const emptyArr: T[] = [];
  return emptyArr.concat(
    ...arr.map((item) => {
      const child: T[] = (item[path] as any) as T[];
      if (Array.isArray(child)) {
        return [item].concat(...flatTree(child, path));
      }
      return item;
    }),
  );
}

const isDev = (): boolean => {
  const { NODE_ENV } = process.env;
  return NODE_ENV === 'development';
};

const formatDate = (date: number) => moment(date).format('YYYY-MM-DD HH:mm:ss');

const getRouteAuthority = (path: string, routeData: Route[]) => {
  let authorities: string[] | string | undefined;
  routeData.forEach((route) => {
    // match prefix
    if (pathRegexp(`${route.path}/(.*)`).test(`${path}/`)) {
      if (route.authority) {
        authorities = route.authority;
      }
      // exact match
      if (route.path === path) {
        authorities = route.authority || authorities;
      }
      // get children authority recursively
      if (route.routes) {
        authorities = getRouteAuthority(path, route.routes) || authorities;
      }
    }
  });
  return authorities;
};

// 排列组合
const permuteUnique = (arr: any) => {
  const results: any[] = [];
  const result: any[] = [];
  if (!arr.length) return results;
  dfs(arr, 0);

  function dfs(list: any, index: number) {
    for (let i = 0; i < list[index].length; i += 1) {
      result[index] = list[index][i];
      if (index !== list.length - 1) {
        dfs(list, index + 1);
      } else {
        results.push(result.join(','));
      }
    }
  }
  return results;
};



export function arrToTree<T extends BaseTree>(arr: T[]) {
  const parentMap = arr.reduce((p, n) => {
    return { ...p, [n.id]: n }
  }, {})

  let i = 0;
  const result = []
  while (i < arr.length) {
    const item = arr[i]
    i += 1
    const parent = parentMap[item.pid]
    if (parent) {
      if (parent.children) {
        parent.children.push(item)
      } else {
        parent.children = [item]
      }
      continue
    }
    result.push(item)
  }
  return result
}


export const fenToYuan = (data: any, keys: Array<string>) => {
  keys.forEach((key: string) => {
    data[key] = data[key] ? (data[key] / 100).toFixed(2) : 0
  });
  return data;
}

const downloadFile = (link: string) => {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', link)
  xhr.responseType = 'blob'
  xhr.send()
  xhr.onload = function () {
    const fileBlob = xhr.response;
    console.log(fileBlob)
    const fileUrl = URL.createObjectURL(fileBlob)
    console.log(fileUrl)
    const ele = document.createElement('a')
    ele.setAttribute('href', fileUrl)
    ele.setAttribute('download', "")
    ele.click()
    ele.innerHTML = '下载'
    document.body.appendChild(ele)
  }
}


const isNilAndEmpty = (val: any) => val !== '' && !isNil(val);

const arrayToObject = (arr: any[], id = 'id', label = 'label') => arr.reduce((pre, next) => { pre[next[id]] = next[label]; return pre; }, {});


export {
  isUrl,
  isNilAndEmpty,
  deleteNullOrUndefinedField,
  replaceRouter,
  getPageQuery,
  deepFlatten,
  flatTree,
  isDev,
  formatDate,
  getRouteAuthority,
  permuteUnique,
  arrayToObject,
  downloadFile
};
